#include <Includes.h>
#include <DRV_Neul_DA.h>
//#include <SVS_Para.h>
#include <Opp_ErrorCode.h>
#include <OPP_Debug.h>
//#include <esp_wifi.h>

ST_DISCRETE_SAVE_PARA g_stDisParaDefault = {
	.udwDiscreteWin = DIS_DEFAULT_WINDOWS,
	.udwDiscreteInterval = DIS_DEFAULT_INTERVAL,
};
static ST_DISCRETE_PARA g_stDisPara;

static ST_DISCRETE_ENABLE g_stDisEnable = {
	.enableH = DIS_ENABLE_H,
	.enableL = DIS_ENABLE_L,
};

static ST_ATTACH_TIME g_stAttachTime = {
	.startTick = 0,
	.endTick = 0,
};


void DAEc600sAttStart()
{
    Ec600sStSet(EC600S_DEV_PWROFF);
}

ST_DA_DEV g_stDaDev[]=
{
    {EN_DEV_TYPE_EC600S,DAEc600sAttStart}
};


/**
@brief 离散参数写入flash
@param pstDisSavePara 离散参数
@return 0成功,非0失败
**/
U32 DASetDiscreteParaToFlash(ST_DISCRETE_SAVE_PARA *pstDisSavePara)
{
    //noted by wangtao
	/*int ret;

	ret = AppParaWrite(APS_PARA_MODULE_APS_DA, DISCRETEWIN_ID, (unsigned char* )pstDisSavePara, sizeof(ST_DISCRETE_SAVE_PARA));
	if(OPP_SUCCESS != ret){
		DEBUG_LOG(DEBUG_MODULE_NEUL, DLL_ERROR, "NeulBc28SetDiscreteParaToFlash fail ret %d\r\n",ret);
		return ret;
	}*/
	return OPP_SUCCESS;
}

/**
@brief 从flash获取离散参数
@param pstDisSavePara 离散参数
@return 0成功,非0失败
**/
U32 DAGetDiscreteParaFromFlash(ST_DISCRETE_SAVE_PARA *pstDisSavePara)
{
    //noted by wangtao
	/*int ret;
	unsigned int len = sizeof(ST_DISCRETE_SAVE_PARA);

	ret = AppParaRead(APS_PARA_MODULE_APS_DA, DISCRETEWIN_ID, (unsigned char* )pstDisSavePara, &len);
	if(OPP_SUCCESS != ret){
		DEBUG_LOG(DEBUG_MODULE_NEUL, DLL_ERROR, "NeulBc28GetDiscreteParaFromFlash fail ret %d\r\n",ret);
		return OPP_FAILURE;
	}
	return OPP_SUCCESS;*/
	return OPP_FAILURE;
}

/**
@brief 离散参数恢复默认值
@param
@return 0成功,非0失败
**/
int DAFactoryReset()
{
    int ret;
	ret = DASetDiscreteParaToFlash(&g_stDisParaDefault);
	if(OPP_SUCCESS != ret){
		return OPP_FAILURE;
	}
	DASetDiscretePara(&g_stDisParaDefault);
    return 0;
}

/**
@brief 设置缓存中离散参数
@param pstDisSavePara 离散参数
@return 0成功,非0失败
**/
U32 DASetDiscretePara(ST_DISCRETE_SAVE_PARA *pstDisSavePara)
{
	MUTEX_LOCK(g_stDisPara.mutex, MUTEX_WAIT_ALWAYS);
	if(pstDisSavePara->udwDiscreteWin > DIS_WINDOW_MAX_SECOND)
		g_stDisPara.udwDiscreteWin = DIS_WINDOW_MAX_SECOND;
	else
		g_stDisPara.udwDiscreteWin = pstDisSavePara->udwDiscreteWin;
	g_stDisPara.udwDiscreteInterval = pstDisSavePara->udwDiscreteInterval;
	MUTEX_UNLOCK(g_stDisPara.mutex);
	return 0;
}

/**
@brief 获取缓存中离散参数
@param pstDisSavePara 离散参数
@return 0成功,非0失败
**/
U32 DAGetDiscretePara(ST_DISCRETE_SAVE_PARA *pstDisSavePara)
{

	MUTEX_LOCK(g_stDisPara.mutex, MUTEX_WAIT_ALWAYS);
	if(g_stDisPara.udwDiscreteWin > DIS_WINDOW_MAX_SECOND)
		pstDisSavePara->udwDiscreteWin = DIS_WINDOW_MAX_SECOND;
	else
		pstDisSavePara->udwDiscreteWin = g_stDisPara.udwDiscreteWin;
	pstDisSavePara->udwDiscreteInterval = g_stDisPara.udwDiscreteInterval;
	MUTEX_UNLOCK(g_stDisPara.mutex);
	return 0;
}

/**
@brief 设置离散窗口
@param disWin 离散窗口
@return 0成功,非0失败
**/
U32 DASetDiscreteWindow(U32 disWin)
{
	MUTEX_LOCK(g_stDisPara.mutex, MUTEX_WAIT_ALWAYS);
	g_stDisPara.udwDiscreteWin = disWin;
	MUTEX_UNLOCK(g_stDisPara.mutex);

	return 0;
}

/**
@brief 获取离散窗口
@param
@return 离散窗口
**/
U32 DAGetDiscreteWindow(void)
{
	U32 disWin;

	MUTEX_LOCK(g_stDisPara.mutex, MUTEX_WAIT_ALWAYS);
	disWin = g_stDisPara.udwDiscreteWin;
	MUTEX_UNLOCK(g_stDisPara.mutex);
	return disWin;
}

/**
@brief 获取离散间隔
@param
@return 离散间隔
**/
U32 DAGetDiscreteScale(void)
{
	U32 disScale;

	MUTEX_LOCK(g_stDisPara.mutex, MUTEX_WAIT_ALWAYS);
	disScale = g_stDisPara.udwDiscreteInterval;
	MUTEX_UNLOCK(g_stDisPara.mutex);
	return disScale;
}

/**
@brief 设置离散开启或关闭
@param
@return 0成功，非0失败
**/
U32 DASetDisEnable(U32 enable)
{
	MUTEX_LOCK(g_stDisEnable.mutex, MUTEX_WAIT_ALWAYS);
	if(DIS_DISABLE == enable){
		g_stDisEnable.enableH = DIS_DISABLE_H;
		g_stDisEnable.enableL = DIS_DISABLE_L;
	}else{
		g_stDisEnable.enableH = DIS_ENABLE_H;
		g_stDisEnable.enableL = DIS_ENABLE_L;
	}
	MUTEX_UNLOCK(g_stDisEnable.mutex);
	return 0;
}

/**
@brief 设置离散开启或关闭,不带信号量操作
@param
@return 0成功，非0失败
**/
U32 DASetDisEnableWithoutMutex(U32 enable)
{
	if(DIS_DISABLE == enable){
		g_stDisEnable.enableH = DIS_DISABLE_H;
		g_stDisEnable.enableL = DIS_DISABLE_L;
	}else{
		g_stDisEnable.enableH = DIS_ENABLE_H;
		g_stDisEnable.enableL = DIS_ENABLE_L;
	}
	return 0;
}

/**
@brief 获取离散开启或关闭状态
@param
@return 离散开关状态
**/
U32 DAGetDisEnable(void)
{
	U32 enable;

	MUTEX_LOCK(g_stDisEnable.mutex, MUTEX_WAIT_ALWAYS);
	if(DIS_DISABLE_H == g_stDisEnable.enableH && DIS_DISABLE_L == g_stDisEnable.enableL){
		enable = DIS_DISABLE;
	}else{
		enable = DIS_ENABLE;
	}
	MUTEX_UNLOCK(g_stDisEnable.mutex);
	return enable;
}


/******************************************************************************
Function    : OppGetNBConOffset
Description : 获取网络附着的偏移时间
Note        : (none)
Input Para  : @disPeriodWnd  离散的时间窗口 单位 秒
               @disIntvlInSnd 离散点的间隔时间 单位 秒
               @mac1    mac地址右第二字节 f9 (24:0a:c4:28:f9:6c)
               @mac0    mac地址右第一字节 6c (24:0a:c4:28:f9:6c)
 Output Para : @outDisOffset
                                      根据输入参数算出的离散偏移时间 单位秒
Return      : OPP_SUCCESS 成功
                             OPP_FAIL   参数错误等
******************************************************************************/
U8 OppGetDisOffsetSecond(U32 disPeriodWnd, U32 disIntvl, U8 mac1,U8 mac0,U32* outDisOffset)
{
     U32 wnd  = disPeriodWnd;
     U32 intvl=  disIntvl;
     U32 wndMod = 1;
     //U32 wndIntrvl = 1;
     U32 intrvlMod = 1;
     U32 offseH = 0;
     U32 offseL = 0;
     if( NULL == outDisOffset){
	 	return OPP_FAILURE;
     }

     if(wnd > DIS_WINDOW_MAX_SECOND){
	 	wnd = DIS_WINDOW_MAX_SECOND;
     }
     if(0 == wnd){
	 	wnd = 1;
     }
     if(intvl > wnd){
	 	intvl = wnd;
     }
     if(0 == intvl ){
	 	intvl = 1;
     }

     wndMod = wnd/intvl;
     if(0 == wndMod){
	 	wndMod = 1;
     }

     intrvlMod = intvl/DIS_INTRVL_SECOND;
     if(0 == intrvlMod){
	 	intrvlMod = 1;
     }
     offseH = (mac0 % wndMod) * intvl;
     offseL = ((mac1&0x0F) % intrvlMod)*DIS_INTRVL_SECOND;
     * outDisOffset = offseH + offseL;
     if((* outDisOffset) > wnd){
	 	(* outDisOffset) = wnd;
     }
     if((* outDisOffset) > DIS_WINDOW_MAX_SECOND){
	 	(* outDisOffset) = DIS_WINDOW_MAX_SECOND;
     }
     return OPP_SUCCESS;
}

/**
@brief 获取离散时间,单位s
@param
@return 离散时间
**/
U32 DADisOffsetSecondGet(void)
{
    //noted by wangtao
	/*int ret;
	unsigned char mac[6] = {0};
	U32 disOffset;
	ST_DISCRETE_SAVE_PARA stDisSavePara;

	esp_wifi_get_mac(WIFI_IF_STA, mac);
	NeulBc28GetDiscretePara(&stDisSavePara);
	ret = OppGetDisOffsetSecond(stDisSavePara.udwDiscreteWin,stDisSavePara.udwDiscreteInterval,mac[4],mac[5],&disOffset);
	if(OPP_SUCCESS != ret){
		disOffset = DIS_WINDOW_MAX_SECOND;
	}
	if(disOffset > DIS_WINDOW_MAX_SECOND){
		disOffset = DIS_WINDOW_MAX_SECOND;
	}

	return disOffset;*/
	return 0;
}

/**
@brief 设置离散开始时间,单位ms
@param
@return
**/
int DASetAttachStartTime(void)
{
	MUTEX_LOCK(g_stAttachTime.mutex, MUTEX_WAIT_ALWAYS);
	g_stAttachTime.startTick = OppTickCountGet();
	MUTEX_UNLOCK(g_stAttachTime.mutex);
	return 0;
}

/**
@brief 设置离散结束时间,单位ms
@param
@return
**/
int DASetAttachEndTime(void)
{
	MUTEX_LOCK(g_stAttachTime.mutex, MUTEX_WAIT_ALWAYS);
	g_stAttachTime.endTick = OppTickCountGet();
	MUTEX_UNLOCK(g_stAttachTime.mutex);
	return 0;
}

/**
@brief 附着耗时,单位ms
@param
@return
**/
U32 DAGetAttachEplaseTime(void)
{
	U32 eplase;

	MUTEX_LOCK(g_stAttachTime.mutex, MUTEX_WAIT_ALWAYS);
	eplase = g_stAttachTime.endTick - g_stAttachTime.startTick;
	MUTEX_UNLOCK(g_stAttachTime.mutex);

	return eplase;
}

/**
@brief 获取相对离散偏移tick值,单位ms
@param
@return
**/
U32 DAAttachDisTick(void)
{
	static U8 first = 1;
	//static U32 tick = 0;
	static U32 offset = 0;

	if(first){
		offset = NeulBc28DisOffsetSecondGet()*1000;
		first = 0;
	}

	if(OppTickCountGet() > offset)
		return (OppTickCountGet()-offset);
	else
		return 0;
}

/**
@brief 离散附着管理初始化
@param
@return
**/
int DAInit()
{
    int ret;
	ST_DISCRETE_SAVE_PARA stDisPara;

	MUTEX_CREATE(g_stDisPara.mutex);
	MUTEX_CREATE(g_stDisEnable.mutex);
	MUTEX_CREATE(g_stAttachTime.mutex);

	ret = DAGetDiscreteParaFromFlash(&stDisPara);
	if(OPP_SUCCESS == ret){
		DASetDiscretePara(&stDisPara);
	}else{
		DASetDiscretePara(&g_stDisParaDefault);
	}
    return 0;
}

/**
@brief 离散附着管理主任务
@param
@return
**/
int DALoop()
{
    static U32 tick=0;
    int i;
    static int disover=0;

    //离散结束
    if(disover)
        return 0;

    if(DIS_DISABLE==DAGetDisEnable())
    {
        for(i=0;i<sizeof(g_stDaDev)/sizeof(ST_DA_DEV);i++)
            g_stDaDev[i].pfunc();
        disover=1;
    }
    else
    {
        if(tick==0)
        {
            tick=OppTickCountGet();
        }

        if(OppTickCountGet() -tick > DADisOffsetSecondGet()*1000)
        {
            for(i=0;i<sizeof(g_stDaDev)/sizeof(ST_DA_DEV);i++)
                g_stDaDev[i].pfunc();
            tick=0;
            disover=1;
        }
    }
    return 0;
}

/*定义别名，兼容老BC28函数*/
U32 NeulBc28SetDiscreteParaToFlash(ST_DISCRETE_SAVE_PARA *pstDisSavePara) __attribute__((weak,  alias("DASetDiscreteParaToFlash")));
U32 NeulBc28GetDiscreteParaFromFlash(ST_DISCRETE_SAVE_PARA *pstDisSavePara) __attribute__((weak,  alias("DAGetDiscreteParaFromFlash")));
U32 NeulBc28SetDiscretePara(ST_DISCRETE_SAVE_PARA *pstDisSavePara) __attribute__((weak,  alias("DASetDiscretePara")));
U32 NeulBc28GetDiscretePara(ST_DISCRETE_SAVE_PARA *pstDisSavePara) __attribute__((weak,  alias("DAGetDiscretePara")));
U32 NeulBc28SetDiscreteWindow(U32 disWin) __attribute__((weak,  alias("DASetDiscreteWindow")));
U32 NeulBc28GetDiscreteWindow(void) __attribute__((weak,  alias("DAGetDiscreteWindow")));
U32 NeulBc28GetDiscreteScale(void) __attribute__((weak,  alias("DAGetDiscreteScale")));
U32 NeulBc28SetDisEnable(U32 enable) __attribute__((weak,  alias("DASetDisEnable")));
U32 NeulBc28SetDisEnableWithoutMutex(U32 enable) __attribute__((weak,  alias("DASetDisEnableWithoutMutex")));
U32 NeulBc28GetDisEnable(void) __attribute__((weak,  alias("DAGetDisEnable")));
U32 NeulBc28DisOffsetSecondGet(void) __attribute__((weak,  alias("DADisOffsetSecondGet")));
int NeulBc28SetAttachStartTime(void) __attribute__((weak,  alias("DASetAttachStartTime")));
int NeulBc28SetAttachEndTime(void) __attribute__((weak,  alias("DASetAttachEndTime")));
U32 NeulBc28GetAttachEplaseTime(void) __attribute__((weak,  alias("DAGetAttachEplaseTime")));
U32 NeulBc28AttachDisTick(void) __attribute__((weak,  alias("DAAttachDisTick")));


